Single Sign On - SSO
Implementation required to perform SSO
- The first step to begin implementing the SSO flow is to expose an endpoint with a public signing key. See Jwks to learn more and how to obtain this key.
- Create an ID token for the logged-in user, signed with the private key corresponding to the public key exposed at the Jwks endpoint. Below is an example payload and a programmatic implementation in C#:
{
"sub": "{logged-in user's CPF}",
"jti": "e2e3b202-19e9-46dc-b061-c5f22eb34194",
"name": "USER NAME",
"email": "user@email.com",
"phone_number": "{user's phone number}", // e.g. 5511000000000
"exp": 1706299657,
"iss": "{base path of the jwks endpoint}", // e.g. https://id.sandbox.btgpactual.com
"aud": "btg:empresas:companies:{cnpj}" // CNPJ of the company whose account will be opened
}
var claims = new Claim[]
{
new Claim(JwtRegisteredClaimNames.Sub, ""),
new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()),
new Claim("name", ""),
new Claim("email", ""),
new Claim("phone_number", ""),
};
var rsaParameters = rsaKeyForSigning.ExportParameters(true);
var rsaSecurityKey = new RsaSecurityKey(rsaParameters);
var signingCredentials = new SigningCredentials(rsaSecurityKey, SecurityAlgorithms.RsaSha256);
var tokenOptions = new JwtSecurityToken(
issuer: iss,
audience: "btg:empresas:companies:{cnpj_onboarding}",
claims: claims,
expires: DateTime.Now.AddMinutes(2),
signingCredentials: signingCredentials
);
var tokenHandler = new JwtSecurityTokenHandler();
var idToken = tokenHandler.WriteToken(tokenOptions);
- After signing the ID token, you must retrieve the public encryption key from the BTG Pactual Empresas jwks endpoint
using var httpClient = new HttpClient();
var btgIdJwksEndpoint = "https://id.btgpactual.com/.well-known/jwks";
var jwksResponse = httpClient.GetStringAsync(btgIdJwksEndpoint).Result;
var jwksData = JObject.Parse(jwksResponse);
var encryptionKeyData = jwksData["keys"].FirstOrDefault(k => k["use"].ToString() == "enc");
string e = encryptionKeyData["e"].ToString();
string n = encryptionKeyData["n"].ToString();
Jwk rsaEncryptionKey = new Jwk(e, n);
- With the public encryption key, you must now use it to generate a JWE, which is simply the JWT of the encrypted ID token.
var headers = new Dictionary<string, object>
{
{ "kid", encryptionKeyData["kid"].ToString() }
};
var recipients = new JweRecipient[]
{
new JweRecipient(JweAlgorithm.RSA_OAEP, rsaEncryptionKey, headers)
};
string encryptedJweIdToken = JWE.Encrypt(idToken, recipients, JweEncryption.A256GCM, mode: SerializationMode.Compact);
- With the JWE in hand, you must create a RAR (rich authorization request) as shown below:
{
"type": "btg:empresas:apps:b2b:onboarding",
"idp": "{parceiro_idp}", // partner's idp registered in BtgId
"principal": "{parceiro_client_id}",
"resource": "btg:empresas:companies:{cnpj_onboarding}",
"privileges": "btg:empresas:gatekeeper:apps:onboarding-enrichment"
}
var authorizationDetails = WebUtility.UrlEncode(JsonConvert.SerializeObject(new[]
{
new {
type = "btg:empresas:apps:b2b:onboarding",
idp = "{parceiro_idp}", // partner's idp registered in BtgId
principal = "{parceiro_client_id}",
resource = "btg:empresas:companies:{cnpj_onboarding}",
privileges = new string[] { "btg:empresas:gatekeeper:apps:onboarding-enrichment" }
}
}));
- After creating the RAR, redirect to the following address, filling in the fields with the data obtained throughout the flow:
https://app.empresas.btgpactual.com/conta-pj-btg?idp_hint={parceiro_idp}&acr_values={parceiro_idp}:sso&id_token_hint={encryptedJweIdToken}&authorization_details={authorizationDetails}&redirect=L2NhZGFzdHJvL3BhcmNlaXJvWhere:
idp_hint: Field corresponding to the "idp" present in the RAR.acr_values: Field corresponding to the "idp" present in the RAR.id_token_hint: Field corresponding to the encrypted JWE.authorization_details: Field corresponding to theauthorizationDetailsvariable.redirect: Fixed field with valueL2NhZGFzdHJvL3BhcmNlaXJv